/*!
 * \file GeneradorClique.h
 *
 * \date May 18, 2014
 * \author correa
 */
#ifndef GENERADORCLIQUE_H_
#define GENERADORCLIQUE_H_

#include <DoubleValueArray.h>
#include <SeparatorParameters.h>
#include <Grafo.h>
#include <list>

using namespace std;

class GeneradorClique
{
	bool		_isDerived;
protected:
	const VertexSet *			_vertices;
	const ValueArray<double>&	_pesos;
	VertexSet&					_Rsuelto;
	Lista&						_orden;			//!< orden decreciente de los vértices del grafo según los valores de los pesos
	Lista&						_restante;

	GeneradorClique(GeneradorClique * ec);
public:
	GeneradorClique(const VertexSet * vertices, const ValueArray<double> * pesos, bool creciente=false);
	virtual ~GeneradorClique();

	GeneradorClique * newInstance(Grafo * g, const SeparatorParameters * par);

	int operator [](const int e) { return _orden[e]; };
	int const operator [](const int e) const { return _orden[e]; };
	int cantidad() const { return _orden.cantidad(); };

	virtual bool hasNext() { cout << "EleccionClique factory." << endl; throw(-1); };
	virtual bool nextClique(ProjectableCliqueSet * c) { cout << "EleccionClique factory." << endl; throw(-1); };
	virtual bool nextCliqueMaximal(ProjectableCliqueSet * c) { cout << "EleccionClique factory." << endl; throw(-1); };
	virtual bool cliqueSuelta(const VertexSet * subgrafo, ProjectableCliqueSet * c) { cout << "EleccionClique factory." << endl; throw(-1); };
	virtual bool cliqueSueltaMaximal(const VertexSet * subgrafo, ProjectableCliqueSet * c) { cout << "EleccionClique factory." << endl; throw(-1); };
	virtual bool cliqueNonArista(ProjectableCliqueSet * c) { cout << "EleccionClique factory." << endl; throw(-1); };
};

/*! \class EleccionClique
 * \brief Enumera cliques maximales pesadas de tamaño máximo especificado
 *
 * Los vértices son ordenados según los valores de las variables respectivas en la solución.
 * El número máximo de cliques enumeradas es especificado en el constructor.
 */
class GeneradorCliqueConGrafo : public GeneradorClique
{
	friend class GeneradorClique;

	const Grafo * 				_grafo;
	const SeparatorParameters * _param;
	VertexSet**					_RR;			//!< conjunto de vértices a enumerar por nivel de la recursión
	VertexSet*					_RRsuelto;
	Lista						_clique;		//!< lista de vértices en la clique actual. Los vértices son representados por sus indices en _orden
	double						_cliqueWeight;

	/*! \fn EleccionClique(Grafo& g, DoubleValueArray& sol, double p, int sz)
	 * \brief Cree una nueva instancia
	 *
	 * \param g El grafo
	 * \param sol Solución usada como pesos de los vértices
	 * \param par Parametros, incluyendo peso mínimo para vértice ser agregado a clique, número máximo de cliques enumeradas y tamaño máximo de las cliques enumeradas
	 */
	GeneradorCliqueConGrafo(GeneradorClique * ec, Grafo * g, const SeparatorParameters * par);
	bool nextCliqueParaMaximal(ProjectableCliqueSet * c);
public:
	~GeneradorCliqueConGrafo();
	/*! bool hasNext()
	 * \brief Responde si aún hay una nueva clique a enumerar
	 *
	 * \return \c TRUE si hay una clique
	 */
	bool hasNext();
	/*! \fn int nextClique(Clique& c)
	 * \brief Sigue la enumeración con una clique más.
	 *
	 * \return número de vértices en la clique encontrada. Si no encuentra clique pesada, retorna 0.
	 */
	bool nextClique(ProjectableCliqueSet * c);
	bool nextCliqueMaximal(ProjectableCliqueSet * c);
	/*! \fn int cliqueSuelta(VertexSet& subgrafo, VertexSet& c, int sizec)
	 * \brief Construye una clique golosa en un subgrafo especificado
	 *
	 * \param subgrafo conjunto de vértices donde buscar la clique
	 * \param c conjunto de vértices de la clique encontrada
	 */
	bool cliqueSuelta(const VertexSet * subgrafo, ProjectableCliqueSet * c);
	bool cliqueSueltaMaximal(const VertexSet * subgrafo, ProjectableCliqueSet * c);
	bool cliqueNonArista(ProjectableCliqueSet * c);
};

#endif /* GENERADORCLIQUE_H_ */
